﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BuildPlannerLib.Buildings;
using BuildPlannerLib.Enums;
using BuildPlannerLib.PlayerActions;
using BuildPlannerLib.SimEvents;
using BuildPlannerLib.Terran.Buildings;
using BuildPlannerLib.Terran.Enums;

namespace BuildPlannerLib.PlayerActions
{
    // Derived class from Action for producing Terran upgrades
    public class ProduceUpgrade : PlayerAction
    {
        // Field for the upgrade being resourced
        public Upgrade Upgrade;

        // Field for the production facility
        public IndividualBuilding Building;

        // Constructor with parameters for build and unit
        public ProduceUpgrade(Build build, Upgrade upgrade)
        {
            Build = build;
            Upgrade = upgrade;
            MineralCost = Upgrade.MineralCost;
            GasCost = Upgrade.GasCost;
            TimeDuration = Upgrade.TimeDuration;
            Description = "Research " + Upgrade.Name;
            LongDescription = "Researching the upgrade " + Upgrade.Name + " at " + Upgrade.ProducedFrom;
        }

        // Evaluates whether there is mineral income or enough minerals, whether there is gas income or enough gas, 
        // whether the upgrade has started yet, whether the requirement building is started, and whether the production
        // building is started
        public override bool RequirementsFilled()
        {
            ProductionBuilding building = Build.Player.GetBuilding(Upgrade.ProducedFrom) as ProductionBuilding;
            Building requirementBuilding = null;
            if (Upgrade.Requirement != null)
                requirementBuilding = Build.Player.GetBuilding(Upgrade.Requirement);
            Error = null;

            if (building == null)
            {
                Error = "Invalid production building.";
                return false;
            }

            if (building.Started == 0)
            {
                Error = "There are no production buildings that can produce this upgrade.";
                return false;
            }

            if (building is AddonBuilding)
            {
                AddonBuilding addonBuilding = (AddonBuilding)building;
                if (!addonBuilding.IndividualBuildings.Exists(delegate(IndividualBuilding i)
                {
                    IndividualAddonBuilding a = i as IndividualAddonBuilding;
                    return a.AddonType == AddonType.TechLab;
                }))
                {
                    Error = "There are no production buildings that can produce this upgrade.";
                    return false;
                }
            }

            if (requirementBuilding != null && requirementBuilding.Started == 0)
            {
                Error = "The required building \"" + Upgrade.Requirement + "\" has not been built.";
                return false;
            }

            if (Upgrade.Status != UpgradeStatus.NotStarted)
            {
                Error = "The upgrade has already been started.";
                return false;
            }

            return base.RequirementsFilled();
        }

        // Evaluates if there are enough minerals, enough gas, requirement building is finished, and production facility is not in-use
        public override bool StartCheck()
        {
            ProductionBuilding building = Build.Player.GetBuilding(Upgrade.ProducedFrom) as ProductionBuilding;
            Building requirementBuilding = null;
            if (Upgrade.Requirement != null)
                requirementBuilding = Build.Player.GetBuilding(Upgrade.Requirement);

            if (requirementBuilding != null && requirementBuilding.GetCount() == 0)
                return false;

            bool availableBuilding = false;
            if (building is AddonBuilding)
            {
                AddonBuilding addonBuilding = (AddonBuilding)building;
                availableBuilding = addonBuilding.IndividualBuildings.Exists(delegate(IndividualBuilding i)
                {
                    IndividualAddonBuilding a = i as IndividualAddonBuilding;
                    return a.AddonType == AddonType.TechLab && !a.AddonInUse;
                });
            }
            else
            {
                availableBuilding = building.IndividualBuildings.Exists(delegate(IndividualBuilding i)
                {
                    return !i.InUse;
                });
            }
            if (!availableBuilding)
                return false;

            return base.StartCheck();
        }

        // Spends the minerals, spends the gas, puts the production building in-use and adds the event to finish the action
        public override void StartAction()
        {
            ProductionBuilding building = Build.Player.GetBuilding(Upgrade.ProducedFrom) as ProductionBuilding;

            base.StartAction();

            if (building is AddonBuilding)
            {
                AddonBuilding addonBuilding = building as AddonBuilding;
                Building = addonBuilding.IndividualBuildings.Find(delegate(IndividualBuilding i)
                {
                    IndividualAddonBuilding a = i as IndividualAddonBuilding;
                    return !a.AddonInUse && a.AddonType == AddonType.TechLab;
                }) as IndividualAddonBuilding;
                IndividualAddonBuilding b = Building as IndividualAddonBuilding;
                b.StartAddonProduction();
            }
            else
            {
                Building = building.IndividualBuildings.Find(delegate(IndividualBuilding i)
                {
                    return !i.InUse;
                });
                Building.StartProduction();
            }
            Upgrade.Status = UpgradeStatus.Started;
        }

        // Sets the production facility from being in-use and finishes the upgrade
        public override void FinishAction()
        {
            IndividualAddonBuilding addonBuilding = Building as IndividualAddonBuilding;

            base.FinishAction();

            if (addonBuilding != null)
                addonBuilding.FinishAddonProduction();
            else
                Building.FinishProduction();

            Upgrade.Status = UpgradeStatus.Finished;
        }
    }
}
